package com.yuuko.yuukoapi.project.system.controller

import cn.dev33.satoken.annotation.SaCheckPermission
import com.yuuko.yuukoapi.common.request.PageParam
import com.yuuko.yuukoapi.common.response.AjaxResult
import com.yuuko.yuukoapi.common.response.None
import com.yuuko.yuukoapi.common.response.SelectOptions
import com.yuuko.yuukoapi.framework.extension.findPage
import com.yuuko.yuukoapi.model.system.Roles
import com.yuuko.yuukoapi.model.system.by
import com.yuuko.yuukoapi.model.system.dto.RolesListSpec
import com.yuuko.yuukoapi.model.system.dto.RolesListView
import com.yuuko.yuukoapi.model.system.dto.RolesUpdateInput
import com.yuuko.yuukoapi.repository.system.RolesRepository
import org.babyfish.jimmer.Page
import org.babyfish.jimmer.sql.ast.mutation.SaveMode
import org.babyfish.jimmer.sql.kt.fetcher.newFetcher
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

@RestController
@RequestMapping("/system/role")
class RolesController(
    val rolesRepository: RolesRepository
) {
    @SaCheckPermission("System:Role:List")
    @GetMapping("/list")
    fun getRoleList(
        page: PageParam,
        spec: RolesListSpec
    ): AjaxResult<Page<RolesListView>> {
        val result = rolesRepository.findPage(page, spec, newFetcher(Roles::class).by {
            allScalarFields()
            menus()
        })
        val formatResult = Page(result.rows.map { RolesListView(it) }, result.totalRowCount, result.totalPageCount)
        return AjaxResult.ok(formatResult)
    }

    @SaCheckPermission("System:Role:Create")
    @PostMapping
    fun createRole(
        @RequestBody input: RolesUpdateInput
    ): AjaxResult<None?> {
        rolesRepository.save(input)
        return AjaxResult.ok()
    }

    @SaCheckPermission("System:Role:Edit")
    @PutMapping("/{id}")
    fun updateRole(
        @PathVariable id: String,
        @RequestBody input: RolesUpdateInput
    ): AjaxResult<None?> {
        rolesRepository.save(
            input.toEntity { this.id = id },
            mode = SaveMode.UPDATE_ONLY
        )
        return AjaxResult.ok()
    }

    @SaCheckPermission("System:Role:Delete")
    @DeleteMapping("/{id}")
    fun deleteRole(@PathVariable id: String) {
        rolesRepository.deleteById(id)
    }

    @GetMapping("/options")
    fun getRoleOptions(): AjaxResult<List<SelectOptions>> {
        val roles = rolesRepository.findAllByStatus(1)
        val result = roles.map { SelectOptions(it.id, it.name) }
        return AjaxResult.ok(result)
    }
}